template <class T>
inline T& Vector4<T>::operator[](unsigned int i)
{
	assert(i >= 0 && i < 4);
	switch(i)
	{
	case 0:
		return x;
	case 1:
		return y;
	case 2:
		return z;
	default:
		return w;
	}
}

template <class T>
inline T Vector4<T>::length() const
{
	return sqrt(x * x + y * y + z * z + w * w);
}

template <class T>
inline T Vector4<T>::lengthSquared() const
{
	return (x * x + y * y + z * z + w * w);
}

template <class T>
inline bool Vector4<T>::operator==( const Vector4<T>& other ) const
{
	return (x == other.x && y == other.y && z ==other.z && w == other.w);
}

template <class T>
inline bool Vector4<T>::operator!=( const Vector4<T>& other ) const
{
	return (x != other.x || y != other.y || z != other.z || w != other.w);
}

template <class T>
inline bool Vector4<T>::isNull() const
{
	return (abs(x) < EPSILON && abs(y) < EPSILON && abs(z) < EPSILON && abs(w) < EPSILON);
}

template <class T>
inline void Vector4<T>::set( T _x, T _y, T _z, T _w )
{
	x = _x; y = _y; z = _z; w = _w;
}

template <class T>
inline void Vector4<T>::setNull()
{
	x = y = z = w = 0;
}

template <class T>
inline void Vector4<T>::normalize()
{
	T len = length();
	if (abs(len) < EPSILON)
	{
		x = y = z = 0;
	}
	else
	{
		x = x / len;
		y = y / len;
		z = z / len;
		w = w / len;
	}
}

template <class T>
inline Vector4<T>& Vector4<T>::addequal(const Vector4<T>& rhs)
{
	x += rhs.x;
	y += rhs.y;
	z += rhs.z;

	return(*this);
}

template <class T>
inline Vector4<T>& Vector4<T>::minusequal(const Vector4<T>& rhs)
{
	x -= rhs.x;
	y -= rhs.y;
	z -= rhs.z;

	return(*this);
}

template <class T>
inline Vector4<T> Vector4<T>::operator+(const Vector4<T>& other) const
{
	Vector4<T> result;
	result.x = x + other.x;
	result.y = y + other.y;
	result.z = z + other.z;
	result.w = w + other.w;

	return result;
}

template <class T>
inline Vector4<T>& Vector4<T>::operator+=( const Vector4<T>& other )
{
	x += other.x;
	y += other.y;
	z += other.z;
	w += other.w;

	return (*this);
}

template <class T>
inline Vector4<T> Vector4<T>::operator-(const Vector4<T>& other) const
{
	Vector4<T> result;
	result.x = x - other.x;
	result.y = y - other.y;
	result.z = z - other.z;
	result.w = w - other.w;

	return result;
}

template <class T>
inline Vector4<T>& Vector4<T>::operator-=(const Vector4<T>& other)
{
	x -= other.x;
	y -= other.y;
	z -= other.z;
	w -= other.w;

	return (*this);
}

template <class T>
inline Vector4<T> Vector4<T>::operator-() const
{
	Vector4<T> result; 
	result.x = -x;
	result.y = -y;
	result.z = -z;
	result.w = -w;

	return result;
}

template <class T>
inline T Vector4<T>::dot(const Vector4<T>& vector) const
{
	return x * vector.x + y * vector.y + z * vector.z + w * vector.w;
}

template <class T>
T Vector4<T>::dot(const Vector4<T>& vector1, const Vector4<T>& vector2)
{
	return vector1.x * vector2.x + vector1.y * vector2.y + vector1.z * vector2.z + vector1.w * vector2.w;
}

template <class T>
inline Vector4<T> Vector4<T>::operator*(T scalar) const
{
	Vector4<T> result;
	result.x = x * scalar;
	result.y = y * scalar;
	result.z = z * scalar;
	result.w = w * scalar;

	return result;
}

template <class T>
inline Vector4<T>& Vector4<T>::operator*=(T scalar)
{
	x *= scalar;
	y *= scalar;
	z *= scalar;
	w *= scalar;

	return (*this);
}